package vip.zhenzicheng.test.juc.threadlocal;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 强、软、弱、虚引用案例
 *
 * @author zhenzicheng
 * @date 2022-09-08 14:44
 */
public class ReferenceCase {

  public static void main(String[] args) throws InterruptedException {
    // strongRef();
    // softRef();
    // weakRef();
    // phantomRef();
  }

  private static void phantomRef() {
    MyObject myObject = new MyObject();
    ReferenceQueue<MyObject> referenceQueue = new ReferenceQueue<>();
    PhantomReference<MyObject> phantomReference = new PhantomReference<>(myObject, referenceQueue);
    // System.out.println(phantomReference.get()); // 总是返回 null，无法访问引用对象
    List<byte[]> list = new ArrayList<>();
    new Thread(() -> {
      while (true) {
        try {
          TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        list.add(new byte[1024 * 1024]); // -Xms10m -Xmx10m
        System.out.println(phantomReference.get() + "\tlist add ok");
      }
    }, "t1").start();

    new Thread(() -> {
      while (true) {
        Reference<? extends MyObject> reference = referenceQueue.poll();
        if (reference != null) {
          System.out.println("----有虚对象回收加入了队列");
          break;
        }
      }
    }, "t2").start();
  }

  private static void weakRef() {
    WeakReference<MyObject> weakReference = new WeakReference<>(new MyObject());
    System.out.println("---- gc before 内存够用, weakReference: " + weakReference.get());
    System.gc(); // 通知 GC，但是没有将弱引用置为 null
    System.out.println("---- gc after 内存够用, weakReference: " + weakReference.get());
  }

  // 软引用，设置VM参数 -Xms10m 限制堆内存最大10m
  private static void softRef() throws InterruptedException {
    SoftReference<MyObject> softReference = new SoftReference<>(new MyObject());
    // System.out.println("----softReference: " + softReference.get());
    System.gc();
    TimeUnit.SECONDS.sleep(1);
    System.out.println("----gc after 内存够用时, softReference: " + softReference.get());
    try {
      byte[] bytes = new byte[20 * 1024 * 1024]; // 尝试分配20m对象，导致OOM
    } catch (OutOfMemoryError error) {
      System.out.println("内存溢出");
    } finally {
      System.out.println("---- gc after 内存不够用时， softReference: " + softReference.get());
    }
  }

  // 强引用demo
  private static void strongRef() throws InterruptedException {
    MyObject myObject = new MyObject();
    System.out.println("gc before: " + myObject);
    myObject = null;
    System.gc();
    TimeUnit.SECONDS.sleep(1);
  }
}

class MyObject {

  @Override
  protected void finalize() throws Throwable {
    System.out.println("invoke finalize method!");
  }
}
